Added gtk_cell_renderer_get_aligned_area() and class vfunc.
authorTristan Van Berkom <tristan.van.berkom@gmail.com>
Thu, 25 Nov 2010 08:41:26 +0000 (17:41 +0900)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Thu, 25 Nov 2010 08:41:26 +0000 (17:41 +0900)
Since a cell renderer might use more space than the natural
size when recieving expand space it's impossible to know how
much space is actually used to render content.

Adding this virtual method to allow text renderers to implement
it, the base default method uses height-for-width apis and aligns
the cell assuming the renderer uses a fixed size.

This commit removes the similar code from gtkcellarea and
subclasses.

gtk/gtkcellarea.c
gtk/gtkcellarea.h
gtk/gtkcellareabox.c
gtk/gtkcellrenderer.c
gtk/gtkcellrenderer.h
gtk/gtkcellrenderertext.c

index 55b6570ab2b6e4b847679f07fa0f9c12b35443bc..e68fb653df16adb24343909a126ba55dfe5cec5d 100644 (file)
@@ -2575,7 +2575,7 @@ gtk_cell_area_activate_cell (GtkCellArea          *area,
          gtk_cell_area_set_edited_cell (area, renderer);
          gtk_cell_area_set_edit_widget (area, editable_widget);
 
-         gtk_cell_area_aligned_cell_area (area, widget, renderer, &inner_area, &edit_area);
+         gtk_cell_renderer_get_aligned_area (renderer, widget, flags, &inner_area, &edit_area);
          
          /* Signal that editing started so that callers can get 
           * a handle on the editable_widget */
@@ -2672,55 +2672,6 @@ gtk_cell_area_inner_cell_area (GtkCellArea        *area,
   inner_area->height -= focus_line_width * 2;
 }
 
-void
-gtk_cell_area_aligned_cell_area (GtkCellArea        *area,
-                                GtkWidget          *widget,
-                                GtkCellRenderer    *renderer,
-                                const GdkRectangle *cell_area,
-                                GdkRectangle       *aligned_area)
-{
-  GtkCellAreaPrivate *priv;
-  gint                opposite_size, x_offset, y_offset;
-
-  g_return_if_fail (GTK_IS_CELL_AREA (area));
-  g_return_if_fail (GTK_IS_CELL_RENDERER (renderer));
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-  g_return_if_fail (cell_area != NULL);
-  g_return_if_fail (aligned_area != NULL);
-
-  priv = area->priv;
-
-  *aligned_area = *cell_area;
-
-  /* Trim up the aligned size */
-  if (gtk_cell_renderer_get_request_mode (renderer) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
-    {
-      gtk_cell_renderer_get_preferred_height_for_width (renderer, widget, 
-                                                       aligned_area->width, 
-                                                       NULL, &opposite_size);
-
-      aligned_area->height = MIN (opposite_size, aligned_area->height);
-    }
-  else
-    {
-      gtk_cell_renderer_get_preferred_width_for_height (renderer, widget, 
-                                                       aligned_area->height, 
-                                                       NULL, &opposite_size);
-
-      aligned_area->width = MIN (opposite_size, aligned_area->width);
-    }
-
-  /* offset the cell position */
-  _gtk_cell_renderer_calc_offset (renderer, cell_area, 
-                                 gtk_widget_get_direction (widget),
-                                 aligned_area->width, 
-                                 aligned_area->height,
-                                 &x_offset, &y_offset);
-
-  aligned_area->x += x_offset;
-  aligned_area->y += y_offset;
-}
-
 void
 gtk_cell_area_request_renderer (GtkCellArea        *area,
                                GtkCellRenderer    *renderer,
index d457d81e21bee0763330da23e683fe1e5fdbee6d..5611e65845e98354e2ffceeb95876023b8511e3b 100644 (file)
@@ -333,14 +333,6 @@ void                  gtk_cell_area_inner_cell_area                (GtkCellArea
                                                                    const GdkRectangle *cell_area,
                                                                    GdkRectangle       *inner_area);
 
-/* Aligns a cell renderer into cell_area by requesting it's size ... used for focus and cell edit areas */
-void                  gtk_cell_area_aligned_cell_area              (GtkCellArea        *area,
-                                                                   GtkWidget          *widget,
-                                                                   GtkCellRenderer    *renderer,
-                                                                   const GdkRectangle *cell_area,
-                                                                   GdkRectangle       *aligned_area);
-
-
 /* Request the size of a cell while respecting the cell margins (requests are margin inclusive) */
 void                  gtk_cell_area_request_renderer               (GtkCellArea        *area,
                                                                    GtkCellRenderer    *renderer,
index 1e2ce41e8277f86703a723b636806cf1e416c925..8950c53c0fb6e693b9ffce53fc277bbbe9bfb1d2 100644 (file)
@@ -1094,7 +1094,7 @@ gtk_cell_area_box_render (GtkCellArea          *area,
            {
              GdkRectangle cell_focus;
 
-             gtk_cell_area_aligned_cell_area (area, widget, cell->renderer, &inner_area, &cell_focus);
+             gtk_cell_renderer_get_aligned_area (cell->renderer, widget, flags, &inner_area, &cell_focus);
 
              /* Accumulate the focus rectangle for all focus siblings */
              if (first_focus_cell)
index 4b6680a2388b879628a6f1d26fe54a09482ca89c..d7b77ed364b36660029e9db46cd3858c9e7217f8 100644 (file)
@@ -97,7 +97,11 @@ static void gtk_cell_renderer_real_get_preferred_width_for_height(GtkCellRendere
                                                                   gint                     height,
                                                                   gint                    *minimum_width,
                                                                   gint                    *natural_width);
-
+static void gtk_cell_renderer_real_get_aligned_area              (GtkCellRenderer         *cell,
+                                                                 GtkWidget               *widget,
+                                                                 GtkCellRendererState     flags,
+                                                                 const GdkRectangle      *cell_area,
+                                                                 GdkRectangle            *aligned_area);
 
 
 struct _GtkCellRendererPrivate
@@ -192,6 +196,7 @@ gtk_cell_renderer_class_init (GtkCellRendererClass *class)
   class->get_preferred_height           = gtk_cell_renderer_real_get_preferred_height;
   class->get_preferred_width_for_height = gtk_cell_renderer_real_get_preferred_width_for_height;
   class->get_preferred_height_for_width = gtk_cell_renderer_real_get_preferred_height_for_width;
+  class->get_aligned_area               = gtk_cell_renderer_real_get_aligned_area;
 
   /**
    * GtkCellRenderer::editing-canceled:
@@ -1236,6 +1241,67 @@ gtk_cell_renderer_real_get_preferred_width_for_height (GtkCellRenderer *cell,
   gtk_cell_renderer_get_preferred_width (cell, widget, minimum_width, natural_width);
 }
 
+
+/* Default implementation assumes that a cell renderer will never use more
+ * space than it's natural size (this is fine for toggles and pixbufs etc
+ * but needs to be overridden from wrapping/ellipsizing text renderers) */
+static void
+gtk_cell_renderer_real_get_aligned_area (GtkCellRenderer         *cell,
+                                        GtkWidget               *widget,
+                                        GtkCellRendererState     flags,
+                                        const GdkRectangle      *cell_area,
+                                        GdkRectangle            *aligned_area)
+{
+  gint opposite_size, x_offset, y_offset;
+  gint natural_size;
+
+  g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (cell_area != NULL);
+  g_return_if_fail (aligned_area != NULL);
+
+  *aligned_area = *cell_area;
+
+  /* Trim up the aligned size */
+  if (gtk_cell_renderer_get_request_mode (cell) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
+    {
+      gtk_cell_renderer_get_preferred_width (cell, widget, 
+                                            NULL, &natural_size);
+
+      aligned_area->width = MIN (aligned_area->width, natural_size);
+
+      gtk_cell_renderer_get_preferred_height_for_width (cell, widget, 
+                                                       aligned_area->width, 
+                                                       NULL, &opposite_size);
+
+      aligned_area->height = MIN (opposite_size, aligned_area->height);
+    }
+  else
+    {
+      gtk_cell_renderer_get_preferred_height (cell, widget, 
+                                             NULL, &natural_size);
+
+      aligned_area->height = MIN (aligned_area->width, natural_size);
+
+      gtk_cell_renderer_get_preferred_width_for_height (cell, widget, 
+                                                       aligned_area->height, 
+                                                       NULL, &opposite_size);
+
+      aligned_area->width = MIN (opposite_size, aligned_area->width);
+    }
+
+  /* offset the cell position */
+  _gtk_cell_renderer_calc_offset (cell, cell_area, 
+                                 gtk_widget_get_direction (widget),
+                                 aligned_area->width, 
+                                 aligned_area->height,
+                                 &x_offset, &y_offset);
+
+  aligned_area->x += x_offset;
+  aligned_area->y += y_offset;
+}
+
+
 /* An internal convenience function for some containers to peek at the
  * cell alignment in a target allocation (used to draw focus and align
  * cells in the icon view).
@@ -1561,3 +1627,35 @@ gtk_cell_renderer_get_preferred_size (GtkCellRenderer *cell,
        }
     }
 }
+
+/**
+ * gtk_cell_renderer_get_aligned_area:
+ * @cell: a #GtkCellRenderer instance
+ * @widget: the #GtkWidget this cell will be rendering to
+ * @flags: render flags
+ * @cell_area: cell area which would be passed to gtk_cell_renderer_render()
+ * @aligned_area: the return location for the space inside @cell_area that
+ *                would acually be used to render.
+ *
+ * Gets the aligned area used by @cell inside @cell_area. Used for finding
+ * the appropriate edit and focus rectangle.
+ *
+ * Since: 3.0
+ */
+void
+gtk_cell_renderer_get_aligned_area (GtkCellRenderer      *cell,
+                                   GtkWidget            *widget,
+                                   GtkCellRendererState  flags,
+                                   const GdkRectangle   *cell_area,
+                                   GdkRectangle         *aligned_area)
+{
+  GtkCellRendererClass *klass;
+
+  g_return_if_fail (GTK_IS_CELL_RENDERER (cell));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (cell_area != NULL);
+  g_return_if_fail (aligned_area != NULL);
+
+  klass = GTK_CELL_RENDERER_GET_CLASS (cell);
+  klass->get_aligned_area (cell, widget, flags, cell_area, aligned_area);
+}
index 736569ccea28fe9462fe01e168584fdf5bc3bb6a..03d9df5130cc228a2b1d1d7d03dab7a19b44e114 100644 (file)
@@ -111,6 +111,11 @@ struct _GtkCellRendererClass
                                                           gint                  height,
                                                           gint                 *minimum_width,
                                                           gint                 *natural_width);
+  void               (* get_aligned_area)                (GtkCellRenderer      *cell,
+                                                          GtkWidget            *widget,
+                                                         GtkCellRendererState  flags,
+                                                          const GdkRectangle   *cell_area,
+                                                          GdkRectangle         *aligned_area);
   void               (* get_size)                        (GtkCellRenderer      *cell,
                                                           GtkWidget            *widget,
                                                           const GdkRectangle   *cell_area,
@@ -177,6 +182,12 @@ void               gtk_cell_renderer_get_preferred_size             (GtkCellRend
                                                                      GtkWidget          *widget,
                                                                      GtkRequisition     *minimum_size,
                                                                      GtkRequisition     *natural_size);
+void               gtk_cell_renderer_get_aligned_area               (GtkCellRenderer    *cell,
+                                                                    GtkWidget          *widget,
+                                                                    GtkCellRendererState flags,
+                                                                    const GdkRectangle *cell_area,
+                                                                    GdkRectangle       *aligned_area);
+
 #ifndef GTK_DISABLE_DEPRECATED
 void             gtk_cell_renderer_get_size       (GtkCellRenderer      *cell,
                                                   GtkWidget            *widget,
index a93f16c9dcb3c7f49a600e01b042b6ab882b9935..f7df6b140c1220f71af265b0969718cfd41217e1 100644 (file)
@@ -84,6 +84,13 @@ static void       gtk_cell_renderer_text_get_preferred_height_for_width (GtkCell
                                                                          gint                   width,
                                                                          gint                  *minimum_height,
                                                                          gint                  *natural_height);
+static void       gtk_cell_renderer_text_get_aligned_area               (GtkCellRenderer       *cell,
+                                                                        GtkWidget             *widget,
+                                                                        GtkCellRendererState   flags,
+                                                                        const GdkRectangle    *cell_area,
+                                                                        GdkRectangle          *aligned_area);
+
+
 
 enum {
   EDITED,
@@ -240,6 +247,7 @@ gtk_cell_renderer_text_class_init (GtkCellRendererTextClass *class)
   cell_class->get_preferred_width = gtk_cell_renderer_text_get_preferred_width;
   cell_class->get_preferred_height = gtk_cell_renderer_text_get_preferred_height;
   cell_class->get_preferred_height_for_width = gtk_cell_renderer_text_get_preferred_height_for_width;
+  cell_class->get_aligned_area = gtk_cell_renderer_text_get_aligned_area;
 
   g_object_class_install_property (object_class,
                                    PROP_TEXT,
@@ -1731,30 +1739,8 @@ get_size (GtkCellRenderer    *cell,
   if (height)
     *height = ypad * 2 + rect.height;
 
-  /* The minimum size for ellipsized labels is ~ 3 chars */
   if (width)
-    {
-      if (priv->ellipsize || priv->width_chars > 0)
-       {
-         PangoContext *context;
-         PangoFontMetrics *metrics;
-         gint char_width;
-
-         context = pango_layout_get_context (layout);
-          metrics = pango_context_get_metrics (context,
-                                               gtk_widget_get_style (widget)->font_desc,
-                                               pango_context_get_language (context));
-
-         char_width = pango_font_metrics_get_approximate_char_width (metrics);
-         pango_font_metrics_unref (metrics);
-         
-         *width = xpad * 2 + (PANGO_PIXELS (char_width) * MAX (priv->width_chars, 3));
-       }
-      else
-       {
-         *width = xpad * 2 + rect.x + rect.width;
-       }         
-    }
+    *width = xpad * 2 + rect.x + rect.width;
 
   if (cell_area)
     {
@@ -2250,3 +2236,24 @@ gtk_cell_renderer_text_get_preferred_height (GtkCellRenderer *cell,
                                                          minimum_size, natural_size);
 }
 
+static void
+gtk_cell_renderer_text_get_aligned_area (GtkCellRenderer       *cell,
+                                        GtkWidget             *widget,
+                                        GtkCellRendererState   flags,
+                                        const GdkRectangle    *cell_area,
+                                        GdkRectangle          *aligned_area)
+{
+  GtkCellRendererText *celltext = GTK_CELL_RENDERER_TEXT (cell);
+  PangoLayout *layout;
+  gint x_offset = 0;
+  gint y_offset = 0;
+
+  layout = get_layout (celltext, widget, cell_area, flags);
+  get_size (cell, widget, cell_area, layout, &x_offset, &y_offset, 
+           &aligned_area->width, &aligned_area->height);
+
+  aligned_area->x = cell_area->x + x_offset;
+  aligned_area->y = cell_area->y + y_offset;
+
+  g_object_unref (layout);
+}